﻿#region License, Terms and Conditions
//
// Copyright (c) 2008, aspZone.com
// All rights reserved.
//
// Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions are met:
//     * Redistributions of source code must retain the above copyright
//       notice, this list of conditions and the following disclaimer.
//     * Redistributions in binary form must reproduce the above copyright
//       notice, this list of conditions and the following disclaimer in the
//       documentation and/or other materials provided with the distribution.
//     * Neither the name of the <organization> nor the
//       names of its contributors may be used to endorse or promote products
//       derived from this software without specific prior written permission.
//
// THIS SOFTWARE IS PROVIDED BY aspZone.com ``AS IS'' AND ANY
// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
// WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
// DISCLAIMED. IN NO EVENT SHALL <copyright holder> BE LIABLE FOR ANY
// DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
// (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
// LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
// ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
// SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
//
// Author(s):
//  John Rudolf Lewis (http://aspZone.com)
//
#endregion

namespace AspZone.Commerce.Repositories
{
    using System.Collections.Generic;
    using System.Linq;
    using Model = AspZone.Commerce.Model;

    public class CategoryRepository :ICategoryRepository
    {
        public bool IncludeProducts { get; set; }

        public IQueryable<Model.Category> Categories
        {
            get 
            {
                var dataContext = this.CreateDataContext();
                var query = from c in dataContext.Categories
                            select new Model.Category
                            {
                                Id = c.CategoryId,
                                Visible = c.Visible,
                                Image = new AspZone.Commerce.Model.Image { FullsizePath = c.ImageFullsizePath, ThumbnailPath = c.ImageThumbnailPath },
                                LongDescription = c.LongDescription,
                                Name = c.Name,
                                SEOKeywords = c.SEOKeywords,
                                SEOName = c.SEOName,
                                SEOTitle = c.SEOTitle,
                                ShortDescription = c.ShortDescription,
                                SortOrder = c.SortOrder,
                                ParentCategoryId = c.ParentCategoryId,
                                Products = (from pc in c.ProductCategories
                                           where this.IncludeProducts
                                           select new Model.Product
                                           {
                                               Id = pc.Product.ProductId,
                                                DiscountPercent = pc.Product.DiscountPercent,
                                                HandlingCharge = pc.Product.HandlingCharge,
                                                LongDescription = pc.Product.LongDescription,
                                                Name = pc.Product.Name,
                                                Price = pc.Product.Price,
                                                QuantityAvailable = pc.Product.QuantityAvailable,
                                                SEOKeywords = pc.Product.SEOKeywords,
                                                SEOName = pc.Product.SEOName,
                                                SEOTitle = pc.Product.SEOTitle,
                                                ShortDescription = pc.Product.ShortDescription,
                                                Weight = pc.Product.Weight,
                                                Images = (from i in pc.Product.ProductImages
                                                          select new Model.Image
                                                          {
                                                              FullsizePath = i.FullsizePath,
                                                              ThumbnailPath = i.ThumbnailPath
                                                          }).ToList(),
                                                Properties = (from prop in pc.Product.ProductProperties
                                                              select new Model.ProductProperty
                                                              {
                                                                  Name = prop.Name,
                                                                  Value = prop.Value
                                                              }).ToList()
                                           }).ToList()
                            };
                return query;

            }
        }

        public void Save(Model.Category category)
        {
            using (var dataContext = this.CreateDataContext())
            {
                var dbCategory = new Database.Category
                {
                    CategoryId = category.Id,
                    LongDescription = category.LongDescription,
                    Name = category.Name,
                    ParentCategoryId = category.ParentCategoryId,
                    SEOKeywords = category.SEOKeywords,
                    SEOName = category.SEOName,
                    SEOTitle = category.SEOTitle,
                    ShortDescription = category.ShortDescription,
                    SortOrder = category.SortOrder,
                    Visible = category.Visible
                };
                if (category.Image != null)
                {
                    dbCategory.ImageFullsizePath = category.Image.FullsizePath;
                    dbCategory.ImageThumbnailPath = category.Image.ThumbnailPath;
                }

                if (this.IncludeProducts)
                {
                    var productCategories = from p in category.Products
                                            select new Database.ProductCategory
                                            {
                                                ProductId = p.Id
                                            };
                    dbCategory.ProductCategories.AddRange(productCategories);
                }

                if (dbCategory.CategoryId == 0)
                {
                    dataContext.Categories.InsertOnSubmit(dbCategory);
                }
                else
                {
                    dataContext.Categories.Attach(dbCategory, true);    
                }

                if (this.IncludeProducts)
                {
                    dataContext.ProductCategories.DeleteAllOnSubmit(dataContext.ProductCategories.Where(pc => pc.CategoryId == dbCategory.CategoryId));
                    dataContext.ProductCategories.InsertAllOnSubmit(dbCategory.ProductCategories);
                }

                dataContext.SubmitChanges();

                category.Id = dbCategory.CategoryId;
            }
        }

        public void Delete(Model.Category category)
        {
            using (var dataContext = this.CreateDataContext())
            {
                dataContext.ProductCategories.DeleteAllOnSubmit(dataContext.ProductCategories.Where(pc => pc.CategoryId == category.Id));
                dataContext.Categories.DeleteAllOnSubmit(dataContext.Categories.Where(c => c.CategoryId == category.Id));

                dataContext.SubmitChanges();
            }
        }

        private Database.CommerceDataContext CreateDataContext()
        {
            var ctx = new Database.CommerceDataContext();
            return ctx;
        }
    }
}
